package com.ccp.dev.qbdms.task;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ccp.dev.core.basic.scheduler.BaseJob;
import com.ccp.dev.core.util.AppUtil;
import com.ccp.dev.core.util.BeanUtils;
import com.ccp.dev.qbdms.dao.WQbdFalProblemresetDao;
import com.ccp.dev.qbdms.util.TikaUtils;
import com.ccp.dev.system.model.SysFile;
import com.ccp.dev.system.service.SysFileService;
import com.google.common.collect.Maps;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.quartz.JobExecutionContext;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.ccp.dev.extend.util.ServiceUtil.getBasePath;
import static com.ccp.dev.qbdms.util.TikaUtils.replaceBlank;
import static java.util.stream.Collectors.toList;

//把普通pojo实例化到spring容器中，相当于配置文件中的<bean id="" class=""/>
@Component
public class EsDataUpdateTask extends BaseJob {


    @Override
    public void executeJob(JobExecutionContext context) throws Exception {
        System.err.println("定时任务启动成功");
        try {
            SysFileService sysFileService =AppUtil.getBean(SysFileService.class);
            RestHighLevelClient restHighLevelClient=AppUtil.getBean(RestHighLevelClient.class);
            WQbdFalProblemresetDao wQbdFalProblemresetDao= AppUtil.getBean(WQbdFalProblemresetDao.class);
            //自动创建index
            GetIndexRequest getIndexRequest = new GetIndexRequest();
            getIndexRequest.indices("zl");
            try {
                boolean a= restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
                if(!a) {
                    CreateIndexRequest index = new CreateIndexRequest("zl");
                    index.alias(new Alias("zl_alias"));
                    //全文检索用的
                    Map<String, Object> ty = Maps.newHashMap();
//        ty.put("type", "text");
                    ty.put("type", "keyword");
                    ty.put("index", true);
//        ty.put("analyzer","keyword");
//        ty.put("null_value",null);
                    Map<String, Object> properties = Maps.newHashMap();
                    //分词 附件用的
                    Map<String, Object> fc = Maps.newHashMap();
                    fc.put("type", "text");
                    fc.put("index", true);
                    fc.put("analyzer", "ik_smart");
                    //只是当数据存储不被搜索的
                    Map<String, Object> index_false = Maps.newHashMap();
                    index_false.put("type", "text");
                    index_false.put("index", false);
                    //keyword类型适用于索引结构化的字段，比如email地址、主机名、状态码和标签。如果字段需要进行过滤(比如查找已发布博客中status属性为published的文章)、排序、聚合。keyword类型的字段只能通过精确值搜索到。
                    Map<String, Object> index_keyword = Maps.newHashMap();
                    index_keyword.put("type", "keyword");
                    index_keyword.put("index", true);
                    index_keyword.put("null_value", "NULL");

                    //只是当数据存储不被搜索的
                    Map<String, Object> date = Maps.newHashMap();
                    date.put("type", "date");
                    date.put("index", true);
                    date.put("format", "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis");
//        properties.put("attachments",properties_fc);
                    properties.put("ID", index_false);
                    properties.put("FILLMAN", ty);
                    properties.put("FILLMANACCOUNT", ty);
                    properties.put("FILLDEPT", ty);
                    properties.put("FILLDEPTID", index_false);
                    properties.put("SECRET", ty);
                    properties.put("F_PROBLEMNAME", ty);
                    properties.put("F_DETECTTIME", date);
                    properties.put("F_MODELSYMBOL", ty);
                    properties.put("F_MODELNAME", ty);
                    properties.put("F_MODELBATCHNO", ty);
                    properties.put("F_MODELTYPE", ty);
                    properties.put("F_WORKPHASE1", ty);
                    properties.put("F_PRODUCTNAME", ty);
                    properties.put("FILLDATE", date);
                    properties.put("F_MODELDEVELOPPHASE", ty);
                    properties.put("F_PRODUCTBATCHNO", ty);
                    properties.put("F_PRODUCECLASS", ty);
                    properties.put("F_BREAKPHASE", ty);
                    properties.put("F_PRODUCTLEVEL", ty);
                    properties.put("F_PRODUCTDESIGNDEPT", ty);
                    properties.put("F_PRODUCTPRODUCEDEPT", ty);
                    properties.put("F_DETECTPLACE", ty);
                    properties.put("F_SUBSYSTEMNAME", ty);
                    properties.put("F_IFFIRSTFLY", ty);
                    properties.put("F_IFSHOOTING", ty);
                    properties.put("F_IFBATCH", ty);
                    properties.put("F_IFTHREE", ty);
                    properties.put("F_PROBLEMRANK", ty);
                    properties.put("F_SOFTHARD", ty);
                    properties.put("F_PROBLEMLEVER", ty);
                    properties.put("F_RESETDAY", ty);
                    properties.put("F_FAILUREDESCRIPTION", ty);
                    properties.put("F_DEEPREASON", ty);
                    properties.put("F_CAUSATION", ty);
                    properties.put("F_FOURREFER", ty);
                    properties.put("F_CAUSATIONCLASS1", ty);
                    properties.put("F_CAUSATIONCLASS2", ty);
                    properties.put("F_CAUSATIONCLASS3", ty);
                    properties.put("F_DUTYDEPT", ty);
                    properties.put("F_DUTYDEPTNATURE", ty);
                    properties.put("F_IFRESET", ty);
                    properties.put("F_RESETTYPE", ty);
                    properties.put("F_RESETTIME", date);
                    properties.put("F_SOLVERESULT", ty);
                    properties.put("F_MEASURECLASS", ty);
                    properties.put("F_CORRECTMEASURE", ty);
                    properties.put("F_OUTDEPTNAME", ty);
                    properties.put("F_RANAGE", ty);
                    properties.put("F_INDUSTY", ty);
                    properties.put("F_OUTNATURE", ty);
                    properties.put("F_SOFTRANK", ty);
                    properties.put("F_ISCHANGE", ty);
                    properties.put("F_CURVERSION", ty);
                    properties.put("F_SHOWVERSION", ty);
                    properties.put("F_UPDATEPERSON", ty);
                    properties.put("F_UPDATEPERSONDEPT", ty);
                    properties.put("F_UPDATEDATE", date);
                    properties.put("F_ORIGINALID", index_false);
                    properties.put("F_PREVIOUSID", index_false);
                    properties.put("F_BELONGDEPTNAME", index_keyword);
                    properties.put("F_CREATEBY", ty);
                    properties.put("F_CREATETIME", date);
                    properties.put("F_UPDATEBY", ty);
                    properties.put("F_UPDATETIME", date);
                    properties.put("F_NUM", ty);
                    properties.put("F_STATUS", ty);
                    properties.put("F_SUPERVISEID", index_false);
                    properties.put("F_MANAGEFACTORANALYSIS", ty);
                    properties.put("F_SKILLRESETTIME", date);
                    properties.put("F_MANAGERESETTIME", date);
                    properties.put("F_IFMATING", ty);
                    //附件 开始
                    properties.put("F_SKILLCERFILE", fc);
                    properties.put("F_MANAGECERFILE", fc);
                    //结束
                    properties.put("F_IFDUTY", ty);
                    properties.put("F_DUTYINVESTIGATIONTYP", ty);
                    properties.put("F_IDENTIFICATION", ty);
                    properties.put("F_CONFIRMDUTYINVEST", ty);
                    properties.put("F_ALLCOUNT", ty);
                    properties.put("F_STATE", ty);
                    properties.put("REPORTSTATUS", ty);
                    properties.put("REPORTREASON", ty);
                    properties.put("F_REPORTSTATUSTEMP", ty);
                    properties.put("F_SUPERVISE", ty);
                    properties.put("RETURNMSG", ty);
                    properties.put("F_REWARDPUNID", index_false);
                    //三院
                    properties.put("QUALITYLEADER", ty);
                    properties.put("F_CAUSATIONCLASS3", ty);
                    //附件名称
                    properties.put("FILENAME", ty);
                    try {

                        XContentBuilder builder = JsonXContent.contentBuilder();
                        builder.startObject()
                                .startObject("mappings")
                                .startObject("WQbdFalProblemreset")
                                .field("properties", properties)
//                 startObject().field("name").startObject().field("index",true).field("type","keyword").endObject().endObject()
                                .endObject()
                                .endObject()
                                .startObject("settings")
                                .field("number_of_shards", 5)
                                .field("number_of_replicas", 0)
                                .endObject()
                                .endObject();
//        number_of_replicas 是数据备份数，如果只有一台机器，设置为0
//
//        number_of_shards  是数据分片数，默认为5，有时候设置为3
                        index.source(builder);
                        restHighLevelClient.indices().create(index, RequestOptions.DEFAULT);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            } catch (IOException e) {
                e.printStackTrace();
            }


                String basePath = getBasePath();
                SimpleDateFormat fm= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//                BulkRequest request = new BulkRequest();
            BulkRequest request_insert = new BulkRequest();
            BulkRequest request_update = new BulkRequest();
            List<IndexRequest> indexRequestList = new ArrayList<>();
            List<UpdateRequest> updateRequestList = new ArrayList<>();


                SearchRequest searchRequest = new SearchRequest();
                searchRequest.indices("zl");
                searchRequest.types("WQbdFalProblemreset");
                SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
                searchSourceBuilder.query(QueryBuilders.matchAllQuery());
                searchRequest.source(searchSourceBuilder);
                try {
                    SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
                    List<Map<String,Object>> qbdFalProblemresetList = wQbdFalProblemresetDao.queryAllES();
                    SearchHits hits = searchResponse.getHits();
                    List<String> list_mysql=wQbdFalProblemresetDao.queryAllID();
                    List<String> list_ES=new ArrayList<>();
                    for (SearchHit hit : hits.getHits()){
                        Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                        list_ES.add(sourceAsMap.get("ID").toString());
                    }

                    // 差集 (list_ES - list_mysql)     需要删除ES库
                    List<String> reduce1 = list_ES.stream().filter(item -> !list_mysql.contains(item)).collect(toList());

                    if (BeanUtils.isNotEmpty(reduce1)){
                        //删除
                        reduce1.stream().forEach(ID ->{
                            DeleteRequest deleteRequest = new DeleteRequest (
                                    "zl",//索引
                                    "WQbdFalProblemreset",//类型
                                    ID);//文档ID
                            try {
                                restHighLevelClient.delete(deleteRequest,RequestOptions.DEFAULT);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        });

                    }
                    System.out.println("---差集 reduce1 (list_ES - list_mysql)---");
                    System.err.println("需要删除的");
                    reduce1.parallelStream().forEach(
                            System.out::println);
                    // 差集 (list_mysql - list_ES) 需要整加es库的
                    List<String> reduce2 = list_mysql.stream().filter(item -> !list_ES.contains(item)).collect(toList());
                    System.out.println("---差集 reduce2 (list_mysql - list_ES)---");
                    System.err.println("需要新增的的");
                    reduce2.parallelStream().forEach(System.out :: println);
                    for (int i=0;i<qbdFalProblemresetList.size();i++){
                        Map<String, Object> map = qbdFalProblemresetList.get(i);
                        Date F_MANAGERESETTIME = (Date) map.get("F_MANAGERESETTIME");
                        if (F_MANAGERESETTIME!=null){
                            map.put("F_MANAGERESETTIME",fm.format(F_MANAGERESETTIME));
                        }
                        Date F_SKILLRESETTIME = (Date) map.get("F_SKILLRESETTIME");
                        if (F_SKILLRESETTIME!=null){
                            map.put("F_SKILLRESETTIME",fm.format(F_SKILLRESETTIME));
                        }
                        Date F_UPDATETIME = (Date) map.get("F_UPDATETIME");
                        if (F_UPDATETIME!=null){
                            map.put("F_UPDATETIME",fm.format(F_UPDATETIME));
                        }

                        Date F_DETECTTIME = (Date) map.get("F_DETECTTIME");
                        if (F_DETECTTIME!=null){
                            map.put("F_DETECTTIME",fm.format(F_DETECTTIME));
                        }

//                        Date F_FILLDATE = (Date) map.get("F_FILLDATE");
//                        if (F_FILLDATE!=null){
//                            map.put("F_FILLDATE",fm.format(F_FILLDATE));
//                        }
                        Date F_RETDAY = (Date) map.get("F_RETDAY");
                        if (F_RETDAY!=null){
                            map.put("F_RETDAY",fm.format(F_RETDAY));
                        }
                        Date F_RETTIME = (Date) map.get("F_RETTIME");
                        if (F_RETTIME!=null){
                            map.put("F_RETTIME",fm.format(F_RETTIME));
                        }
                        Date F_UPDATEDATE = (Date) map.get("F_UPDATEDATE");
                        if (F_UPDATEDATE!=null){
                            map.put("F_UPDATEDATE",fm.format(F_UPDATEDATE));
                        }

                        Date F_CREATETIME = (Date) map.get("F_CREATETIME");
                        if (F_CREATETIME!=null){
                            map.put("F_CREATETIME",fm.format(F_CREATETIME));
                        }
                        Date F_SKILLRETTIME = (Date) map.get("F_SKILLRETTIME");
                        if (F_SKILLRETTIME!=null){
                            map.put("F_SKILLRETTIME",fm.format(F_SKILLRETTIME));
                        }
                        Date F_MANAGERETTIME = (Date) map.get("F_MANAGERETTIME");
                        if (F_MANAGERETTIME!=null){
                            map.put("F_MANAGERETTIME",fm.format(F_MANAGERETTIME));
                        }

                        String fileNames="";
//                   List<Attachment> list =new ArrayList<>();
                        if (map.get("F_SKILLCERFILE") != null) {
                            String F_SKILLCERFILE = map.get("F_SKILLCERFILE").toString();
                            List<Map<String, String>> listObjectFir = (List<Map<String, String>>) JSONArray.parse(F_SKILLCERFILE);
                            String texts = "";
                            for (Map<String, String> stringStringMap : listObjectFir) {
                                String fileName =stringStringMap.get("fileName");
                                SysFile sysFile = sysFileService.getOneById(stringStringMap.get("fileId"));
                                if (BeanUtils.isNotEmpty(sysFile)) {
//                            String fileName = sysFile.getFileName();
                                    fileNames+=fileName;
                                    String path = basePath + File.separator + sysFile.getFilePath();
                                    String text = TikaUtils.fileToString(path);
                                    texts+=text;
                                }
                            }
                            map.put("F_SKILLCERFILE", texts);
                            map.put("FILENAME", fileNames);
                        }
                        if (map.get("F_MANAGECERFILE") != null) {
                            String F_MANAGECERFILE = map.get("F_MANAGECERFILE").toString();
                            List<Map<String, String>> listObjectFir = (List<Map<String, String>>) JSONArray.parse(F_MANAGECERFILE);
                            String texts = "";
                            for (Map<String, String> stringStringMap : listObjectFir) {
                                String fileName =stringStringMap.get("fileName");
                                SysFile sysFile = sysFileService.getOneById(stringStringMap.get("fileId"));
                                if (BeanUtils.isNotEmpty(sysFile)) {
//                            String fileName = sysFile.getFileName();
                                    fileNames+=fileName;
                                    String path = basePath + File.separator + sysFile.getFilePath();
                                    String text = TikaUtils.fileToString(path);
                                    texts+=text;
                                }
                            }
                            map.put("F_MANAGECERFILE", texts);
                            map.put("FILENAME", fileNames);
                        }
                        String jsonString = JSONObject.toJSONString(map);
                        for (SearchHit hit : hits.getHits()){
                            String sourceAsString = hit.getSourceAsString();
                            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                            String ESID=  sourceAsMap.get("ID").toString();
                            if (ESID.equals(map.get("ID").toString())){
                                //更新
                                String ESFUPDATETIME=  sourceAsMap.get("F_UPDATETIME").toString();
                                if (!ESFUPDATETIME.equals(fm.format(F_UPDATETIME))){
                                    UpdateRequest updateRequest = new UpdateRequest  (
                                            "zl",//索引
                                            "WQbdFalProblemreset",//类型
                                            ESID);//文档ID
                                    updateRequest.doc(jsonString,XContentType.JSON);
                                    updateRequestList.add(updateRequest);
//                                    restHighLevelClient.update(updateRequest,RequestOptions.DEFAULT);
                                    continue;
                                }
                            }

                        }
                        //新增
                        if (reduce2.contains(map.get("ID").toString()))   {
//                            request.add(new IndexRequest("zl","WQbdFalProblemreset").opType("create").id(map.remove("ID").toString()).source(jsonString, XContentType.JSON));
                            indexRequestList.add(new IndexRequest("zl", "WQbdFalProblemreset").id(map.get("ID").toString()).source(jsonString, XContentType.JSON));
                        }
                    }
                    for (IndexRequest indexRequest : indexRequestList) {
                        request_insert.add(indexRequest);
                    }
                    for (UpdateRequest updateRequest : updateRequestList) {
                        request_update.add(updateRequest);
                    }
                    if (indexRequestList != null && indexRequestList.size()!=0  ) {
                        restHighLevelClient.bulk(request_insert, RequestOptions.DEFAULT);
                    }
                    if (updateRequestList != null && updateRequestList.size()!=0 ) {
                        restHighLevelClient.bulk(request_update, RequestOptions.DEFAULT);
                    }

                }catch (Exception e){
                    e.printStackTrace();
                }


        }catch (Exception e){
            e.printStackTrace();
        }

                System.err.println("定时任务结束");


    }
}